﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using SlimMath;

/**
 * SlimMath
 * 現状ではHalf,Colorの2つだけを使っている
 * */

delegate bool SetFocusDelegate (Vector3 a, Vector3 b);

namespace MyTestProject {
    public class TestSlimMath {

        /**
         * カラーのテスト
         * */
        [Fact]
        public void TestColor () {
            var color = new SlimMath.Color4 (0x12345678);

            Assert.Equal (0x12 / 255.0f, color.Alpha);
            Assert.Equal (0x34 / 255.0f, color.Red);
            Assert.Equal (0x56 / 255.0f, color.Green);
            Assert.Equal (0x78 / 255.0f, color.Blue);
            Assert.Equal (0x12345678u, (uint)color.ToArgb ());
        }

        /**
         * クオータニオンのテスト
         * */
        [Fact]
        public void TestQuaternionConstructor () {
            var q = Quaternion.RotationAxis (new Vector3 (0, 1, 0), (float)Math.PI / 2.0f);

            // 正規化されずに返ってくる
            var qaxis = q.Axis;
            qaxis.Normalize ();

            Assert.Equal (0.0f, qaxis[0], 4);
            Assert.Equal (1.0f, qaxis[1], 4);
            Assert.Equal (0.0f, qaxis[2], 4);
            Assert.Equal (Math.PI / 2.0f, q.Angle, 4);
        }

        /**
         * 2つのクオータニオンの間の角度を求める。
         * acos(dot(p,q))は4D空間での角度で3D空間ではその2倍な事に注意。
         * 本などでは説明無しに4D空間の角度しか書いてないことが多い
         * */
        [Fact]
        public void TestAngleOfTwoQuaternions () {
            var q1 = Quaternion.RotationAxis (new Vector3 (0, 1, 0), 0);
            var q2 = Quaternion.RotationAxis (new Vector3 (0, 1, 0), (float)Math.PI / 2.0f);

            // x2は3D空間での角度
            var angle = 2 * Math.Acos (Quaternion.Dot (q2, q1));

            Assert.Equal (Math.PI / 2.0f, angle, 4);
        }

        /*
         * 2つのクオータニオンの間の球面補間(slerp)
         * */
        [Fact]
        public void TestSlerp () {
            var q1 = Quaternion.RotationAxis (new Vector3 (0, 1, 0), 0);
            var q2 = Quaternion.RotationAxis (new Vector3 (0, 1, 0), (float)Math.PI / 2.0f);

            Assert.Equal (0, Quaternion.Slerp (q1, q2, 0.0f).Angle, 4);
            Assert.Equal (Math.PI / 4.0f, Quaternion.Slerp (q1, q2, 0.5f).Angle, 4);
            Assert.Equal (Math.PI / 2.0f, Quaternion.Slerp (q1, q2, 1.0f).Angle, 4);
        }
    }
}
